
#include "cli_command.h"
#include "data_store_func.h"
#include "device_resource.h"
#include "lfs2_port.h"
#include "print_rtt.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* ----------------  弱钩子：配置变化后调用  ---------------- */
void mqtt_cli_on_change(void)
{
  MQTT_connet_status = 0;
  write_base_paremeter_to_fs(setting_para);
}

/* ----------------  CLI 命令入口  ---------------- */
BaseType_t mqtt_cli_command(char *pcWriteBuffer, size_t xWriteBufferLen,
                            const char *pcCommandString)
{
  // 定义参数长度临时变量（避免重复计算）
  size_t broker_len = sizeof(setting_para->mqtt_para.MQTT_broker);
  size_t client_len = sizeof(setting_para->mqtt_para.MQTT_client);
  size_t user_len = sizeof(setting_para->mqtt_para.MQTT_user);
  size_t pass_len = sizeof(setting_para->mqtt_para.MQTT_password);

  const char *pcSub = FreeRTOS_CLIGetParameter(pcCommandString, 1, &(BaseType_t){0});
  const char *pcFld = FreeRTOS_CLIGetParameter(pcCommandString, 2, &(BaseType_t){0});
  const char *pcVal = FreeRTOS_CLIGetParameter(pcCommandString, 3, &(BaseType_t){0});

  /* ----------  show  ---------- */
  if (pcSub && strncmp(pcSub, "show", 4) == 0)
  {
    snprintf(pcWriteBuffer, xWriteBufferLen,
             "\r\nMQTT broker : %s:%u\r\n"
             "client      : %s\r\n"
             "user        : %s\r\n"
             "pass        : %s\r\n",
             setting_para->mqtt_para.MQTT_broker,
             setting_para->mqtt_para.MQTT_port,
             setting_para->mqtt_para.MQTT_client,
             setting_para->mqtt_para.MQTT_user[0] ? setting_para->mqtt_para.MQTT_user : "(none)",
             setting_para->mqtt_para.MQTT_user[0] ? setting_para->mqtt_para.MQTT_password : "(none)");
    return pdFALSE;
  }

  /* ----------  set all  ---------- */
  if (pcSub && strncmp(pcSub, "set", 3) == 0 &&
      pcFld && strncmp(pcFld, "all", 3) == 0)
  {

    // 获取第3到第7个参数（broker, port, client, user, password）
    BaseType_t len_broker, len_port, len_client, len_user, len_pass;
    const char *broker_str = FreeRTOS_CLIGetParameter(pcCommandString, 3, &len_broker);
    const char *port_str = FreeRTOS_CLIGetParameter(pcCommandString, 4, &len_port);
    const char *client_str = FreeRTOS_CLIGetParameter(pcCommandString, 5, &len_client);
    const char *user_str = FreeRTOS_CLIGetParameter(pcCommandString, 6, &len_user);
    const char *pass_str = FreeRTOS_CLIGetParameter(pcCommandString, 7, &len_pass);

    // 检查是否所有参数都存在
    if (!broker_str || !port_str || !client_str || !user_str || !pass_str)
    {
      snprintf(pcWriteBuffer, xWriteBufferLen, "\r\nError: Missing parameters. Usage: mqtt set all <broker> <port> <client> <user> <password>\r\n");
      return pdFALSE;
    }

// 安全复制字符串（防止溢出）
#define MIN_CLI(a, b) ((a) < (b) ? (a) : (b))
#define COPY_STR(dst, src, srclen, dstsize)      \
  do                                             \
  {                                              \
    size_t n = MIN_CLI((srclen), (dstsize) - 1); \
    memcpy((dst), (src), n);                     \
    (dst)[n] = '\0';                             \
  } while (0)

    COPY_STR(setting_para->mqtt_para.MQTT_broker, broker_str, len_broker, sizeof(setting_para->mqtt_para.MQTT_broker));
    setting_para->mqtt_para.MQTT_port = (uint16_t)strtoul(port_str, NULL, 10); // 将端口字符串转为整数
    COPY_STR(setting_para->mqtt_para.MQTT_client, client_str, len_client, sizeof(setting_para->mqtt_para.MQTT_client));
    COPY_STR(setting_para->mqtt_para.MQTT_user, user_str, len_user, sizeof(setting_para->mqtt_para.MQTT_user));
    COPY_STR(setting_para->mqtt_para.MQTT_password, pass_str, len_pass, sizeof(setting_para->mqtt_para.MQTT_password));

    snprintf(pcWriteBuffer, xWriteBufferLen,
             "\r\nMQTT all set successfully!\r\n"
             "Broker: %s:%u\r\n"
             "Client: %s\r\n"
             "User  : %s\r\n"
             "Pass  : %s\r\n",
             setting_para->mqtt_para.MQTT_broker,
             setting_para->mqtt_para.MQTT_port,
             setting_para->mqtt_para.MQTT_client,
             setting_para->mqtt_para.MQTT_user[0] ? setting_para->mqtt_para.MQTT_user : "(none)",
             setting_para->mqtt_para.MQTT_password[0] ? setting_para->mqtt_para.MQTT_password : "(none)");
    mqtt_cli_on_change();
    return pdFALSE;
  }
  /* ----------  set single field  ---------- */
  if (pcSub && strncmp(pcSub, "set", 3) == 0 && pcFld)
  {
    if (!pcVal || pcVal[0] == '\0')
    {
      snprintf(pcWriteBuffer, xWriteBufferLen,
               "\r\nUsage: mqtt set <broker|port|client|user|pass> <value>\r\n"
               "Examples:\r\n"
               "  mqtt set broker 192.168.0.1\r\n"
               "  mqtt set port 183\r\n"
               "  mqtt set client myclient\r\n");
      return pdFALSE;
    }

    // Broker 地址
    if (strncmp(pcFld, "broker", 6) == 0)
    {
      strncpy(setting_para->mqtt_para.MQTT_broker, pcVal, broker_len - 1);
      setting_para->mqtt_para.MQTT_broker[broker_len - 1] = '\0';
      snprintf(pcWriteBuffer, xWriteBufferLen, "\r\nMQTT broker set to: %s\r\n", setting_para->mqtt_para.MQTT_broker);
    }
    // 端口（加校验）
    else if (strncmp(pcFld, "port", 4) == 0)
    {
      uint16_t port = (uint16_t)atoi(pcVal);
      if (port == 0 || port > 65535)
      {
        snprintf(pcWriteBuffer, xWriteBufferLen, "\r\nError: Invalid port! Must be 1-65535\r\n");
        return pdFALSE;
      }
      setting_para->mqtt_para.MQTT_port = port;
      snprintf(pcWriteBuffer, xWriteBufferLen, "\r\nMQTT port set to: %u\r\n", setting_para->mqtt_para.MQTT_port);
    }
    // Client ID
    else if (strncmp(pcFld, "client", 6) == 0)
    {
      strncpy(setting_para->mqtt_para.MQTT_client, pcVal, client_len - 1);
      setting_para->mqtt_para.MQTT_client[client_len - 1] = '\0';
      snprintf(pcWriteBuffer, xWriteBufferLen, "\r\nMQTT client set to: %s\r\n", setting_para->mqtt_para.MQTT_client);
    }
    // User
    else if (strncmp(pcFld, "user", 4) == 0)
    {
      strncpy(setting_para->mqtt_para.MQTT_user, pcVal, user_len - 1);
      setting_para->mqtt_para.MQTT_user[user_len - 1] = '\0';
      snprintf(pcWriteBuffer, xWriteBufferLen, "\r\nMQTT user set to: %s\r\n", setting_para->mqtt_para.MQTT_user);
    }
    // Password
    else if (strncmp(pcFld, "pass", 4) == 0)
    {
      strncpy(setting_para->mqtt_para.MQTT_password, pcVal, pass_len - 1);
      setting_para->mqtt_para.MQTT_password[pass_len - 1] = '\0';
      snprintf(pcWriteBuffer, xWriteBufferLen, "\r\nMQTT password set successfully!\r\n");
    }
    // 未知字段
    else
    {
      snprintf(pcWriteBuffer, xWriteBufferLen, "\r\nUnknown field! Support: broker/port/client/user/pass\r\n");
      return pdFALSE;
    }

    mqtt_cli_on_change();
    return pdFALSE;
  }

  // 命令格式错误（优化帮助信息）
  snprintf(pcWriteBuffer, xWriteBufferLen,
           "\r\nMQTT CLI Usage:\r\n"
           "  1. Show config:  mqtt show\r\n"
           "  2. Set single:   mqtt set <field> <value>\r\n"
           "  3. Set all:      mqtt set all <addr> <port> <client> [user] [pass]\r\n"
           "Support fields: broker, port, client, user, pass\r\n");
  return pdFALSE;
}

/* ----------------  CLI 注册表（末尾已含）  ---------------- */
const CLI_Command_Definition_t xMQTTCommand = {
    "mqtt",
    "\r\n\r\nmqtt <show|set> ...     # View / modify MQTT parameters\r\n\r\n",
    mqtt_cli_command,
    -1};
/*=================  底层适配接口（弱符号，可在外部重写） ================*/

/* 默认弱符号实现 —— 返回“假数据”，避免链接错误 */
bool sfp_is_present(void) { return SFP_present; }
bool sfp_link_up(void) { return false; }
uint32_t sfp_link_speed(void)
{
  if (g_sfp_module_status == 0)
  {
    if (g_pSdsMode == SERDES_10GR)
    {
      return 10000;
    }
    else if (g_pSdsMode == SERDES_1000BASEX)
    {
      return 1000;
    }
    else
    {
      return 0;
    }
  }
  else
  {
    return 0;
  }
} /* Mbps */
sfp_mode_t sfp_get_mode(void)
{
  if (setting_para->sfp_auto_flag == 1)
  {
    return SFP_MODE_AUTO;
  }
  else
  {
    switch (setting_para->sfp_type)
    {
    case SERDES_1000BASEX:
      return SFP_MODE_1G;
    case SERDES_10GR:
      return SFP_MODE_10G;
    default:
      return SFP_MODE_UNKNOWN;
    }
  }
}
void sfp_set_auto(void)
{
  setting_para->sfp_auto_flag = 1;
  write_base_paremeter_to_fs(setting_para);
  g_sfp_setting_status = SFP_STATUS_NEED_SET;
}
void sfp_force_1g(void)
{
  setting_para->sfp_auto_flag = 0;
  setting_para->sfp_type = SERDES_1000BASEX;
  write_base_paremeter_to_fs(setting_para);
  g_sfp_setting_status = SFP_STATUS_NEED_SET;
}
void sfp_force_10g(void)
{
  setting_para->sfp_auto_flag = 0;
  setting_para->sfp_type = SERDES_10GR;
  write_base_paremeter_to_fs(setting_para);
  g_sfp_setting_status = SFP_STATUS_NEED_SET;
}

/*=================  工具：模式转字符串  ================*/
static const char *mode2str(sfp_mode_t m)
{
  switch (m)
  {
  case SFP_MODE_AUTO:
    return "none";
  case SFP_MODE_1G:
    return "1G";
  case SFP_MODE_10G:
    return "10G";
  default:
    return "unknown";
  }
}

/* -------------- CLI 处理函数 -------------- */
static BaseType_t sfp_cli_command(char *pcWriteBuffer,
                                  size_t xWriteBufferLen,
                                  const char *pcCommandString)
{
  const char *pcSub;
  BaseType_t xLen;

  pcSub = FreeRTOS_CLIGetParameter(pcCommandString, 1, &xLen);
  if (pcSub == NULL)
  {
    snprintf(pcWriteBuffer, xWriteBufferLen,
             "\nUsage: sfp <mode|auto|1g|10g>\r\n");
    return pdFALSE;
  }

  /* ---------- 查询 ---------- */
  if (strncmp(pcSub, "mode", xLen) == 0)
  {
    bool present = sfp_is_present();
    uint32_t spd = present ? sfp_link_speed() : 0;
    sfp_mode_t mode = sfp_get_mode();

    const char *spd_str = "n/a";
    if (spd == 1000)
      spd_str = "1 Gbps";
    if (spd == 10000)
      spd_str = "10 Gbps";

    snprintf(pcWriteBuffer, xWriteBufferLen,
             "\r\nSFP present: %s\r\n"
             "Link speed : %s\r\n"
             "Auto-neg   : %s\r\n"
             "Force mode : %s\r\n",
             present ? "yes" : "no",
             spd_str,
             mode == SFP_MODE_AUTO ? "on" : "off",
             mode2str(mode));
    return pdFALSE;
  }

  /* ---------- auto ---------- */
  if (strncmp(pcSub, "auto", xLen) == 0)
  {
    sfp_set_auto();
    snprintf(pcWriteBuffer, xWriteBufferLen,
             "\r\nSFP mode switched to: auto (speed-detect enabled)\r\n");
    return pdFALSE;
  }

  /* ---------- 1G ---------- */
  if (strncmp(pcSub, "1g", xLen) == 0)
  {
    sfp_force_1g();
    snprintf(pcWriteBuffer, xWriteBufferLen,
             "\r\nSFP mode switched to: 1G (forced)\r\n");
    return pdFALSE;
  }

  /* ---------- 10G ---------- */
  if (strncmp(pcSub, "10g", xLen) == 0)
  {
    sfp_force_10g();
    snprintf(pcWriteBuffer, xWriteBufferLen,
             "\r\nSFP mode switched to: 10G (forced)\r\n");
    return pdFALSE;
  }

  /* ---------- 未知 ---------- */
  snprintf(pcWriteBuffer, xWriteBufferLen,
           "\r\nUnknown sub-command\r\n");
  return pdFALSE;
}

/* -------------- 注册表：帮助字符串末尾 1 个 \r\n（命令间空一行） -------------- */
const CLI_Command_Definition_t xSFPCommand = {
    "sfp",
    "\r\n\r\nsfp <mode|auto|1g|10g>  # Query / set SFP operating mode\r\n\r\n",
    sfp_cli_command,
    1 /* 必须提供 1 个参数 */
};

void factory_restore_defaults(void)
{
  write_base_paremeter_to_fs(&default_parameter);
}
static BaseType_t factory_cli_command(char *pcWriteBuffer,
                                      size_t xWriteBufferLen,
                                      const char *pcCommandString)
{
  const char *pcConfirm;
  BaseType_t xLen;

  pcConfirm = FreeRTOS_CLIGetParameter(pcCommandString, 1, &xLen);

  if (pcConfirm == NULL)
  {
    snprintf(pcWriteBuffer, xWriteBufferLen,
             "\r\n!! Danger !!  This will erase ALL user settings.\r\n"
             "Type 'factory confirm'  to proceed, or press Enter to cancel.\r\n");
    return pdFALSE;
  }

  if (strncmp(pcConfirm, "confirm", xLen) == 0)
  {
    snprintf(pcWriteBuffer, xWriteBufferLen,
             "Restoring factory defaults...\r\n");
    /* 1. 停止关键任务/断开网络，防止写 Flash 被中断 */
    vTaskSuspendAll(); /* 简单粗暴，也可发事件让任务自杀 */
    /* 2. 擦除参数区并写入出厂值 */
    factory_restore_defaults(); /* 你的实现 */
    /* 3. 软复位 */
    NVIC_SystemReset();
    /* 不会执行到这里 */
    return pdFALSE;
  }

  snprintf(pcWriteBuffer, xWriteBufferLen,
           "\nUnknown option, use 'factory confirm' to proceed.\r\n");
  return pdFALSE;
}

const CLI_Command_Definition_t xFactoryCommand = {
    "factory",
    "\r\n\r\nfactory [confirm]  # restore factory settings (confirm required)\r\n\r\n",
    factory_cli_command,
    -1 /* 参数可选 */
};

/* --------------  专门用于 help 空行的伪命令  -------------- */
static BaseType_t dummy_empty_command(char *pcWriteBuffer,
                                      size_t xWriteBufferLen,
                                      const char *pcCommandString)
{
  /* 永远不应该被执行到，因为命令名是空串 */
  pcWriteBuffer[0] = 0;
  return pdFALSE;
}

const CLI_Command_Definition_t xEmptyLineCommand = {
    "",         /*  空命令名  */
    "\r\n\r\n", /*  只输出空行  */
    dummy_empty_command,
    0 /* 不需要参数 */
};
/* 弱符号：先停业务再复位，可按需重写 */
void vSystemPrepareReset(void)
{
  /* 示例：关闭调度器，停止 DMA/中断 */
  taskDISABLE_INTERRUPTS();
  vTaskSuspendAll();
}

static BaseType_t restart_cli_command(char *pcWriteBuffer,
                                      size_t xWriteBufferLen,
                                      const char *pcCommandString)
{
  const char *pcConfirm;
  BaseType_t xLen;

  pcConfirm = FreeRTOS_CLIGetParameter(pcCommandString, 1, &xLen);

  if (pcConfirm == NULL)
  {
    snprintf(pcWriteBuffer, xWriteBufferLen,
             "\r\n!! Danger !!  This will immediately reboot the system.\r\n"
             "Type 'restart confirm'  to proceed, or press Enter to cancel.\r\n");
    return pdFALSE;
  }

  if (strncmp(pcConfirm, "confirm", xLen) == 0)
  {
    snprintf(pcWriteBuffer, xWriteBufferLen,
             "\r\nRestarting system now...\r\n");
    /* 预留停机钩子 */
    vSystemPrepareReset();
    /* 立即软复位 */
    NVIC_SystemReset();
    /* 不会跑到这里 */
    return pdFALSE;
  }

  snprintf(pcWriteBuffer, xWriteBufferLen,
           "\nUnknown option, use 'restart confirm' to proceed.\r\n");
  return pdFALSE;
}

const CLI_Command_Definition_t xRestartCommand = {
    "restart",
    "\r\n\r\nrestart [confirm]  # immediately reboot system (confirm required)\r\n\r\n",
    restart_cli_command,
    -1 /* 参数可选 */
};
#define VLAN_ENTRY 16 /* 固定 16 个 */
#define VLAN_MIN   1
#define VLAN_MAX   4094
/*  weak  -  替换为你的驱动  */
unsigned int vlanRead(unsigned int idx)
{
  return setting_para->VLAN_TABLE[idx];
}
void vlanWrite(unsigned int idx, unsigned int id)
{
  setting_para->VLAN_TABLE[idx] = id;
  write_base_paremeter_to_fs(setting_para);
  g_vlan_set_status = VLAN_NEED_SET;
}

/*  ---------------- CLI 处理 ---------------- */
static BaseType_t vlanCliCommand(char *pcWriteBuffer,
                                 size_t xWriteBufferLen,
                                 const char *pcCommandString)
{
  const char *pcSub;
  BaseType_t xLen;

  pcSub = FreeRTOS_CLIGetParameter(pcCommandString, 1, &xLen);
  if (pcSub == NULL)
  {
    snprintf(pcWriteBuffer, xWriteBufferLen,
             "\nUsage: vlan show  OR  vlan set index id\r\n");
    return pdFALSE;
  }

  /*  -----  show  -----  */
  if (strncmp(pcSub, "show", xLen) == 0)
  {
    unsigned int n = 0;
    n += snprintf(pcWriteBuffer + n, xWriteBufferLen - n, "\r\n");
    for (unsigned int i = 0; i < VLAN_ENTRY; ++i)
    {

      n += snprintf(pcWriteBuffer + n, xWriteBufferLen - n,
                    "vlan%u:%u\r\n", i + 1, vlanRead(i));
    }
    return pdFALSE;
  }

  /*  -----  set 子命令处理  -----  */
  if (strncmp(pcSub, "set", xLen) == 0)
  {
    BaseType_t lenIdx = 0, lenNew = 0;
    const char *pcIdx = NULL, *pcNew = NULL;
    char idx_buf[16] = {0};   // 存储截取后的索引字符串（带 '\0'）
    char newId_buf[16] = {0}; // 存储截取后的 ID 字符串（带 '\0'）

    /* 1. 获取参数（索引 2=index，索引 3=id） */
    pcIdx = FreeRTOS_CLIGetParameter(pcCommandString, 2, &lenIdx);
    pcNew = FreeRTOS_CLIGetParameter(pcCommandString, 3, &lenNew);

    /* 2. 检查参数是否存在（必须同时存在 index 和 id） */
    if (!pcIdx || lenIdx == 0 || !pcNew || lenNew == 0)
    {
      snprintf(pcWriteBuffer, xWriteBufferLen,
               "\r\nError: need index and id (format: vlan set <index> <id>)\r\n");
      return pdFALSE;
    }

    /* 3. 关键修复：手动截取参数并添加 '\0' 终止符（避免字符串溢出） */
    // 截取 index（最多 15 字符，防止缓冲区溢出）
    lenIdx = (lenIdx > sizeof(idx_buf) - 1) ? sizeof(idx_buf) - 1 : lenIdx;
    memcpy(idx_buf, pcIdx, lenIdx);
    idx_buf[lenIdx] = '\0'; // 手动添加终止符

    // 截取 id（最多 15 字符）
    lenNew = (lenNew > sizeof(newId_buf) - 1) ? sizeof(newId_buf) - 1 : lenNew;
    memcpy(newId_buf, pcNew, lenNew);
    newId_buf[lenNew] = '\0'; // 手动添加终止符

    /* 4. 字符串转数字（此时用处理后的带终止符的缓冲区） */
    char *end = NULL;
    long idx = strtol(idx_buf, &end, 10);
    // 检查是否为有效数字（end 指向终止符才是完整数字）
    if (*end != '\0' || idx < 1 || idx > VLAN_ENTRY)
    {
      snprintf(pcWriteBuffer, xWriteBufferLen,
               "\r\nError: index must be 1 to %u (integer)\r\n", VLAN_ENTRY);
      return pdFALSE;
    }

    long newId = strtol(newId_buf, &end, 10);
    if (*end != '\0' || newId < VLAN_MIN || newId > VLAN_MAX)
    {
      snprintf(pcWriteBuffer, xWriteBufferLen,
               "\r\nError: id must be %u to %u (integer)\r\n", VLAN_MIN, VLAN_MAX);
      return pdFALSE;
    }

    /* 5. 执行写入操作 */
    vlanWrite(idx - 1, (unsigned int)newId);
    snprintf(pcWriteBuffer, xWriteBufferLen,
             "\r\nOK: VLAN index %ld set to ID %ld\r\n", idx, newId);
    return pdFALSE;
  }

  snprintf(pcWriteBuffer, xWriteBufferLen, "\r\nError: bad command\r\n");
  return pdFALSE;
}

const CLI_Command_Definition_t xVLANCommand = {
    "vlan",
    "\r\n\r\nvlan <show| set index id>   # Query / set vlan \r\n\r\n",
    vlanCliCommand,
    -1};
